package dyyx.bladex;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.ConcurrentHashMap;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;

import dyyx.bladex.dto.ApiResult;
import dyyx.bladex.util.RunStatusUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.FullHttpResponse;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.handler.codec.http.HttpVersion;
import io.netty.handler.codec.http.QueryStringDecoder;
import io.netty.handler.codec.http.multipart.Attribute;
import io.netty.handler.codec.http.multipart.HttpPostRequestDecoder;
import io.netty.handler.codec.http.multipart.InterfaceHttpData;
import io.netty.util.CharsetUtil;

public class BladexServerHandler extends ChannelInboundHandlerAdapter {

	private static final String UTF8 = "utf-8";

	private static final String CONTENT_TYPE = "Content-Type";
	private static final String CONTENT_LENGTH = "Content-Length";
	private static final String CONNECTION = "Connection";
	private static final String KEEP_ALIVE = "keep-alive";
	
	private static final Map<String,Object> dataMap = new ConcurrentHashMap<String,Object>();


	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) {
		ctx.flush();
	}

	@Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) {

        if (msg instanceof FullHttpRequest) {
            FullHttpRequest req = (FullHttpRequest) msg;           
            Map<String,String> reqmap = getRequestMap(req);
            //String result = "reqmap="+reqmap;
            
            ApiResult apiResult = new ApiResult();
            
            handle(apiResult,reqmap);
            
            //向客户端发送结果
            doResponse(ctx,req,JSON.toJSONString(apiResult));
        }
    }
	
	
	private void handle(ApiResult result,Map<String,String> map){
		//ApiResult result = new ApiResult();
		String type = map.get("type");
		if(StringUtils.isBlank(type)){
			result.errorCode = "type_blank";
			result.success = false;
			return ;
		}
		type = type.trim();

		if("status".equals(type)){
			result.result = RunStatusUtil.runStatus;
			return ;
		}
		
	    if("put".equals(type)){
	    	
	    	String key = map.get("key");
	    	
	    	if(StringUtils.isBlank(key)){
				result.errorCode = "key_blank";
				result.success = false;

				return ;
			}
	    	
	    	String value = map.get("value");
	    	
	    	if(StringUtils.isBlank(value)){
	    		result.errorCode = "value_blank";
				result.success = false;

				return ;
			}

	    	dataMap.put(key, value);
	    	
	    	
	    	result.msg = type+"_done";

	    	return ;
	    }
	    
        if("remove".equals(type)){
        	
	    	String key = map.get("key");

	    	
	    	if(StringUtils.isBlank(key)){
	    		result.errorCode = "key_blank";
				result.success = false;

				return ;
			}
	    	
	    	dataMap.remove(key);
	    	
	    	result.msg = type+"_done";

	    	return ;
	    }
        
        if("get".equals(type)){
        	
            String key = map.get("key");
	    	
	    	if(StringUtils.isBlank(key)){
	    		result.errorCode = "key_blank";
				result.success = false;

				return ;
			}
	    	
	    	result.result = dataMap.get(key);
	    	
	    	return ;
	    }
        
        if("size".equals(type)){
        	result.result = dataMap.size();
	    	return ;
	    }	
        
        if("clear".equals(type)){
        	dataMap.clear();
        	result.msg = type+"_done";
	    	return ;
	    }	

        result.errorCode = "type_error";
		result.success = false;

		
	}
	
	

	/**
	 * 响应HTTP的请求
	 * 
	 * @param ctx
	 * @param req
	 * @param jsonStr
	 */
	private void doResponse(ChannelHandlerContext ctx, FullHttpRequest req, String result) {

		// boolean keepAlive = HttpUtil.isKeepAlive(req);
		boolean keepAlive = true;
		// byte[] jsonByteByte = jsonStr.getBytes();
		byte[] resultBytes = getBytes(result);
		FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK,
				Unpooled.wrappedBuffer(resultBytes));
		// text/json
		// response.headers().set(CONTENT_TYPE, "text/html");
		// 
		response.headers().set(CONTENT_TYPE, "text/html;charset=utf-8");
		// response.headers().setInt(CONTENT_LENGTH,
		// response.content().readableBytes());
		response.headers().set(CONTENT_LENGTH, response.content().readableBytes());
		
		if (!keepAlive) {
			ctx.write(response).addListener(ChannelFutureListener.CLOSE);
			//System.out.println("keepAlive is false,close,"+new Date());
		} else {
			response.headers().set(CONNECTION, KEEP_ALIVE);

			ctx.write(response);
		}
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
		cause.printStackTrace();
		ctx.close();
	}

	/**
	 * 获取请求的内容
	 * 
	 * @param request
	 * @return
	 */
	private String parseRequestString(FullHttpRequest request) {
		ByteBuf buf = request.content();
		String str = buf.toString(CharsetUtil.UTF_8);
		return str;
	}

	private static byte[] getBytes(String str) {
		try {
			return str.getBytes(UTF8);
		} catch (Throwable e) {
			return new byte[0];
		}
	}
	
	
    public static Map<String, String> getRequestMap(FullHttpRequest req)  {
        
    	//Map<String, String>  map = new HashMap<String,String>();
    	HttpMethod method = req.getMethod();

        Map<String, String> parmMap = new HashMap<>();

        if (HttpMethod.GET == method) {       	
        	String requri = req.getUri();
        	//System.out.println("requestUri="+requri);       	
            // 是GET请求
            QueryStringDecoder decoder = new QueryStringDecoder(requri,CharsetUtil.UTF_8);
        	// System.out.println("requestUri="+decoder.getc);

            /*
            decoder.parameters().entrySet().forEach( entry -> {
                // entry.getValue()是一个List, 只取第一个元素
                parmMap.put(entry.getKey(), entry.getValue().get(0));
            });
            */
            Map<String,List<String>> qmap = decoder.parameters();
            Set<Entry<String,List<String>>> eset = qmap.entrySet();
            List<String> list = null;
            String key = null;
            
            for(Entry<String,List<String>> item:eset){
            	key = item.getKey();
            	list = item.getValue();
            	if(list.size()>0){
                    parmMap.put(key, list.get(0));
            	}
            }
            
        } else if (HttpMethod.POST == method) {
            // 是POST请求
            HttpPostRequestDecoder decoder = new HttpPostRequestDecoder(req);
            decoder.offer(req);

            List<InterfaceHttpData> dataList = decoder.getBodyHttpDatas();

            for (InterfaceHttpData item : dataList) {

               // Attribute data = (Attribute) parm;
               // parmMap.put(data.getName(), data.getValue());
               // bodyHttpData=Mixed: name=tiger,class io.netty.handler.codec.http.multipart.MixedAttribute,Attribute
               // bodyHttpData=Mixed: age=7,class io.netty.handler.codec.http.multipart.MixedAttribute,Attribute

               // System.out.println("bodyHttpData="+item+","+item.getClass()+","+item.getHttpDataType());
               
               if(item instanceof Attribute){
            	   Attribute dataitem = (Attribute) item;
            	   String value = getValue(dataitem);
            	   if(value==null){
            		   continue;
            	   }
            	   parmMap.put(dataitem.getName(), value);
               }
               
            }

        } else {
            // 不支持其它方法
            //throw new MethodNotSupportedException(""); // 这是个自定义的异常, 可删掉这一行
            
        }

        return parmMap;
    }

    
    private static String getValue(Attribute attr){
    	if(attr==null){
    		return null;
    	}
    	try{
    		return attr.getValue();
    	}catch(Throwable e){
    		return null;
    	}
    }

}
